from flask import g
from wtforms.validators import DataRequired, Length, NumberRange, ValidationError
from wtforms.fields import StringField, BooleanField, IntegerField, MultipleFileField
from wtforms import Form, FormField
from bson import ObjectId

from app.validators import BaseForm
from app.db.models.jobs import Job
from app.db.models.alert_groups import AlertGroup
from app.errors import ServerError


class SettingVul(Form):
    high = IntegerField(validators=[NumberRange(min=0, max=1048575)], default=0)
    medium = IntegerField(validators=[NumberRange(min=0, max=1048575)], default=0)
    low = IntegerField(validators=[NumberRange(min=0, max=1048575)], default=0)
    critical = IntegerField(validators=[NumberRange(min=0, max=1048575)], default=0)


class SettingSecurityEvent(Form):
    black_links = IntegerField(validators=[NumberRange(min=0, max=1048575)], default=0)
    broken_links = IntegerField(validators=[NumberRange(min=0, max=1048575)], default=0)
    foreign_links = IntegerField(validators=[NumberRange(min=0, max=1048575)], default=0)
    cryjack = BooleanField(default=True)
    malscan = BooleanField(default=True)


class Settings(Form):
    vul = FormField(SettingVul)
    securityEvent = FormField(SettingSecurityEvent)


class UrlBlackListSetEditForm(BaseForm):
    uid = StringField()
    alertGroupIds = MultipleFileField(default=[])
    notification = MultipleFileField(default={})
    settings = FormField(Settings)

    def validate_uid(self, value):
        if not value.data:
            if g.role.name == '普通用户':
                value.data = g.user.id
            else:
                raise ServerError(msg="'uid' is required.")

        if not isinstance(value.data, ObjectId):
            value.data = ObjectId(value.data)

        return value

    def validate_alertGroupIds(self, value):
        alert_groups = set(str(item.id) for item in AlertGroup.objects.filter(pk__in=value.data, uid=self.uid.data))
        if d := set(value.data) - alert_groups:
            raise ServerError(msg=f"告警组 '{', '.join(d)}' 不存在")


class UrlBlackListSetAddForm(UrlBlackListSetEditForm):
    job_id = StringField(validators=[DataRequired(), Length(min=24, max=24)])

    def validate_job_id(self, value):
        value.data = ObjectId(value.data)

        if not Job.objects.filter(pk=value.data, uid=self.uid.data).first():
            raise ServerError(msg="资产不存在或已被删除")
